//= require <traits/CollisionDetection>

namespace("controls::HtmlControl", {	
	traits : [new MooTools.Events, CollisionDetection],
	
	preInitialize : function(){
		var self = this;
		var args = arguments;
		this.addEvent("model-initialized",   this.initializeElement.bind(this,arguments[0]));
		this.addEvent("element-initialized", this.bindEvents.bind(this));
		this.addEvent("events-initialized",  function preInitialize() {
			self.initialize.apply(self,args);
		});
		
		this.initializeModel.call(self,arguments[0]||{});
		return this;
	},
	

	initializeModel : function(params) {
		params = params||{};
        params.model = (params.model||this.model);
		if(params instanceof js.Model) {
			this.model = params;}
		else {
			var _params = js.extend(this.model||{}, params);
			for(var key in _params) {
				if(typeof _params[key] === "function") {
					this[key] = _params[key].bind(this);
					delete _params[key];}
			}
			this.model = new js.Model(_params.model||{});
		}
		this.fireEvent("model-initialized");
	},
	
	initializeElement : function(params) {
        params = params||{};
        params.element = (params.element||this.element);
		this.element = params.element||document.createElement("div");
		this.initializeChildren();
	},
	
 	initializeChildren : function(){
        
        this.setClassName();
		//var child_nodes = this.getElements("*")||[];
        
		var initialize_node = function(child){
			var ns    = child.getAttribute("ui-type");
			var Klass = (ns && NSRegistry[ns]) ? 
				NSRegistry[ns] : null;
			if(Klass) {new Klass({element : child});}
		}.bind(this);
        //child_nodes.forEach(initialize_node);
        this.applyCssExpressions();
		this.fireEvent("element-initialized");
    },
    
	setClassName: function(){
		if(!this.hasClass(this.classname)){
			this.addClass(this.classname);}
    },
	
	bindEvents : function() {
		var self = this;
        var events = (this["@events"]||this.events);
		if(events) {
			for(customEventName in events) {
				var mapping 	 = events[customEventName];
				var cssSelector  = mapping[0];
				var w3cEventName = mapping[1];
				var handlerFunc  = this[customEventName];
				if(handlerFunc) {
					var res = this.getElements(cssSelector);
					for(var i=0; i<= res.length-1; i++) {
						$(res[i]).addEvent(w3cEventName, handlerFunc.bind(self));}
				}
			}
		}
		for(member in this) {
			if(this.nativeevents.indexOf(member) >= 0) {
				$(this.element).addEvent(member, this[member].bind(this));}
		}
		this.fireEvent("events-initialized");
	},
	
	nativeevents : ("DOMFocusIn DOMFocusOut DOMActivate keyup keydown keypress click mousedown mouseup mouseover mousemove mouseout DOMSubtreeModified DOMNodeInserted DOMNodeRemoved DOMNodeRemovedFromDocument DOMNodeInsertedIntoDocument DOMAttrModified DOMCharacterDataModified load unload abort error change submit reset focus select blur resize scroll selectstart").split(" "),
	
	get : function(key){
		return this.model[key];
	},
	
	set : function(key,val) {
		this.model.set(key,val);
	},

    
	applyCssExpressions: function() {
        var self = this;
        for (var selector in self["@css"]) {
           if(selector.indexOf(">") >= 0) {
                /*var parts = selector.split(">");
                var cssSelector  = parts[0];
                var domEventName = parts[1]; 
                var cssValue     = self["@css"][selector];
                
                
                var elements = (cssSelector.trim() === ".") ? 
                    [this.element]:self.getElements(cssSelector);
                for(var i=0; i<= elements.length-1; i++) {
                    //console.log("applied css expression:" + selector)
                    var el = $(elements[i]);
                        el.addEvent(domEventName, function(e){
                            var val = cssValue;
    					        val = /^\-\>/.test(val) ? val.call(el, e,el):val;
                        });
                }*/
            }
            else {
                var cssSelector  = selector;
                var cssValue     = self["@css"][selector];
                var elements = (cssSelector.trim() === "::") ? 
                    [this.element]:this.getElements(cssSelector); 
                for(var k in cssValue) {
                    cssValue[k] = (/^\-\>/.test(cssValue[k])) ? 
                        cssValue[k].call(self, self):cssValue[k];
                }
                for(var i=0; i<= elements.length-1; i++) {
                    var el = elements[i];
                    $(el).setStyles(cssValue);
                }
            } 
        }
		/*var self = this;
        if(!self["@css"]) return;
		for (css in self["@css"]) {
			var elements = (css.trim() === ".") ? 
                [this.element]:self.getElements(css);
			for(var i=0; i<= elements.length-1; i++) {
                var el = elements[i];
                for (var attrb in self["@css"][css]) {
                    console.log("attrb: " + attrb);
                    if(attrb.indexOf(">") >= 0) {
                        var parts = attrb.split(">");
                        var stylename = parts[0];
                        var eventname = parts[1]; 
                        console.lof("evt:" + eventname)
                        $(el).addEvent(eventname, function(){
                            var val = self["@css"][css][attrb];
    					        val = /^\-\>/.test(val) ? val.call(self, self):val;
                           // $(el).setStyle(stylename, val);
                        });
                    }
                    else {
                      var val = self["@css"][css][attrb];//.call(self, self);
    					    val = /^\-\>/.test(val) ? val.call(self, self):val; 
    					$(el).setStyle(attrb, val);  
                    }
                    
                }
            }
		}*/
	},
    
    load_css: function(url){
		var something_went_wrong = "Error loading stylesheets. Expected an array of style urls or a single url to a stylesheet for this component.";
		var stylesheets = window.loaded_stylesheets;
		var styles = url||this.stylesheets;
		
		if (!stylesheets) {
			window.loaded_stylesheets = {};
			stylesheets = window.loaded_stylesheets;}
		if(styles) {
			if(styles instanceof Array) {
				for(var i=0; i<=styles.length-1; i++) {
					if (!stylesheets[styles[i]]) {
						this.load_css(styles[i]);
					}
				}
			}
			else if(typeof styles === "string") {
				var headID = document.getElementsByTagName("head")[0];
		        var cssNode = document.createElement('link');
		        cssNode.type = 'text/css';
		        cssNode.rel = 'stylesheet';
		        cssNode.href = this.resourcepath(styles);
		        cssNode.media = 'screen';
		        headID.appendChild(cssNode);
				stylesheets[styles] = cssNode;
				return stylesheets[styles];
			}
		}
		else {
			//styles = this.assetpath(this.getClassName() + ".css");
			//throw new Error("TODO: Load any default stylesheets for widget '" + this.getClassName() + "'.  (see: Widget.prototype.load_css()")
		}
    },
    
//    hasClass : function hasClass(classNm){
//        return (this.element && this.element.className.indexOf(classNm) >= 0);
//    },
//    
//    addClass: function addClass(classNm) {
//        if (!this.hasClass(classNm)) {
//            this.element.className += " " + classNm;}
//    },
//
//    setStyles : function() {
//        var args = arguments, styles, element;
//        if(args.length === 2) {
//            styles  = args[1];
//            element = args[0]||this.element;}
//        else if(args.length === 1){
//            element = this.element;
//            styles = args[0];}
//            
//        var elementStyle = element.style, match;
////        if (typeof styles === "string") {
////          element.style.cssText += ';' + styles;
////          return styles.include('opacity') ?
////            element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
////        }
//        for (var property in styles) 
//          if (property === 'opacity') this.setOpacity(styles[property]);
//          else
//            elementStyle[(property == 'float' || property == 'cssFloat') ?
//              (typeof (elementStyle.styleFloat === "undefined") ? 'cssFloat' : 'styleFloat') : property] = styles[property];
//    
//        return element;
//	},
    
    setOpacity: function(value) {
        element = this.element;
        element.style.opacity = (value == 1 || value === '') ? 
            '' : (value < 0.00001) ? 0 : value;
        return element;
    },
    
    fade : function(level) {
      element = this.element;
      level = (level == 1 || level === '') ? '' : (level < 0.00001) ? 0 : level;
      element.style.opacity = level;
      element.style.MozOpacity = level;
      element.style.KhtmlOpacity = level;
      element.style.filter = "alpha(opacity=" + (level * 100) + ");";
    },
    
    addEventListener : function _addEventListener(eventName, callback, capture) {
        if(this.nativeevents.indexOf(eventName) >= 0) {
            return NW.Event.appendHandler(this.element, eventName, callback, capture);
        }
        else {
            return this.addEvent(eventName, callback, capture);
        }
    },
    
//    fadeIn: function fadeIn() {
//        var duration = 1000;   /* 1000 millisecond fade = 1 sec */
//        var steps    = 20;     /* number of opacity intervals   */
//        var delay    = 5000;   /* 5 sec delay before fading out */
//	    for (i = 0; i <= 1; i += (1 / steps)) {
//            setTimeout("setOpacity(" + i + ")", i * duration);};
//	    setTimeout("fadeOut()", delay);
//    },
//    
//    fadeOut: function fadeOut() {
//	    var self = this;
//	    var duration = 1000;   /* 1000 millisecond fade = 1 sec */
//	    var steps    = 20;     /* number of opacity intervals   */
//        var delay    = 5000;   /* 5 sec delay before fading out */
//      for (var i = 0; i <= 1; i += (1 / steps)) {
//        //setTimeout("setOpacity(" + (1 - i) + ")", i * duration);
//        setTimeout(function(){self.fade(1 - i)}, i * duration);};
//      //setTimeout("fadeIn()", duration);
//    }
//
    getElements : function(cssSelector) {
        if(typeof Sly != "undefined")
       	    return Sly.search(cssSelector, this.element);
        else return this.parent(cssSelector);
    }
});


if(typeof MooTools != "undefined") {
	function aspect(meth) {
		return function() {
			return meth.apply(this.element, arguments);
		}
	}
	var proto = controls.HtmlControl.prototype;
	if(MooTools.Element && MooTools.Element.Prototype) {
        var _mootools_Element = MooTools.Element.Prototype;
		for(propNam in _mootools_Element) {
			if(!proto[propNam]) {
				proto[propNam] = aspect(_mootools_Element[propNam]);}
		}
	}
};
